use std::env::args;
use std::ffi::CString;
use std::ptr::null;
use nix::fcntl::{open, OFlag};
use nix::libc::{__errno_location, execvp, printf, setns, strerror};
use nix::sys::stat::Mode;
use crate::utilty::log_error;

pub fn wrap_exec(){
    if args().count()<4{
        log_error("args count error".to_string());
        return;
    }
    exec()
}
pub fn exec() {
    let pid = args().nth(2).expect("no specify pid");
    let exec = args()
        .into_iter()
        .skip(3)
        .map(|arg| CString::new(arg.as_str()).unwrap())
        .collect::<Vec<_>>();
    let mut exec = exec.iter().map(|e| e.as_c_str()).collect::<Vec<_>>();
    let mut exec = exec
        .iter()
        .map(|e| e.as_ptr())
        .chain(Some(null()))
        .collect::<Vec<_>>();

    let namespace_file = ["pid", "ipc", "net", "uts", "mnt"];
    let path = format!("/proc/{pid}/ns");
    for file in namespace_file {
        let absolute_path = format!("{path}/{file}");
        let fd = open(absolute_path.as_str(), OFlag::O_RDONLY, Mode::empty())
            .expect("open ns file failed");
        unsafe {
            if setns(fd, 0) == -1 {
                println!("ns file setns failed");
                printf(c"%s\n".as_ptr(), strerror(*__errno_location()));
            } else {
                println!("ns file {} setns succeeded", file);
            };
        }
    }
    unsafe {
        execvp(exec[0], exec.as_ptr());
        println!("execvp failed");
        printf(c"%s\n".as_ptr(), strerror(*__errno_location()));
    }
}